package net.pulseproject.commons.midi;

import javax.sound.midi.ShortMessage;

import net.pulseproject.commons.midi.entity.MidiMessageStatus;
import net.pulseproject.commons.midi.entity.MidiSocket;
import net.pulseproject.commons.util.MidiUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MessageAnalyzerImpl implements MessageAnalyzer {

	private static final Log LOG = LogFactory.getLog(MessageAnalyzerImpl.class);
	
	@Override
	public final MidiSocket createMidiSocket(final ShortMessage message, final String port) {
		if(message == null) { throw new IllegalArgumentException("message == null"); }
		if(port == null) { throw new IllegalArgumentException("port == null"); }
		if(port.isEmpty()) { throw new IllegalArgumentException("port is empty"); }
		
		LOG.debug("createMidiSocket(message=" + MidiUtil.toString(message) + ", port=[" + port + "])");
		
		final Integer channel = Integer.valueOf(message.getChannel());
		final Integer controllerNumber = this.extractControllerNumber(message);
		return new MidiSocket(port, channel, controllerNumber);
	}
	
	@Override
	public final Integer extractControllerNumber(final ShortMessage message) {
		LOG.debug("extractControllerNumber(message=" + MidiUtil.toString(message) + ")");
		final Integer controllerNumber;
		
		if(this.isControllerMessage(message) == true) {
			controllerNumber = Integer.valueOf(message.getData1());
			// shortMessage.getData2() contains controller value
			
			assert (message.getStatus() - MidiMessageStatus.CONTROLLER_CHANNEL_1.getValue() == message.getChannel());
			
		} else {
			// got a non controller midi message (most likely a note)
			controllerNumber = MidiSocket.IGNORE_CONTROLLER;
		}
		LOG.trace("  ... returning controller number: " + controllerNumber);
		return controllerNumber;
	}
	
	@Override
	public final boolean isControllerMessage(final ShortMessage message) {
		final int messageStatus = message.getStatus();
		// status 176 to 191... Chan 1 to 16 Control/Mode Change
		return messageStatus >= MidiMessageStatus.CONTROLLER_CHANNEL_1.getValue() &&
			   messageStatus <= MidiMessageStatus.CONTROLLER_CHANNEL_16.getValue();
	}
}
